#include "FileUtil.h"
#include "StringUtil.h"
#include <iostream>

#ifdef CXX_LESS_17
#include <sys/stat.h>
#include <limits.h>   
#include <unistd.h>
#endif


AMCAX_EXCHANGE_NAMESPACE_BEGIN 
namespace FileUtil 
{


    std::string GetExtensionWithoutDot(const std::string &path)
    {
#ifndef CXX_LESS_17
        std::string extension =  StringUtil::ToLowerCase(std::filesystem::path(path).extension().string());
        if (!extension.empty() && extension[0] == '.') {
            extension.erase(0, 1);  // 去掉开头的 '.'
        }
        return extension;
#else
        // 找最后一个斜杠（文件名开始处）
        size_t slashPos = path.find_last_of("/\\");
        size_t filenameStart = (slashPos == std::string::npos) ? 0 : slashPos + 1;

        // 找最后一个点（扩展名开始）
        size_t dotPos = path.find_last_of('.');

        // 检查点的位置是否在文件名中
        if (dotPos == std::string::npos || dotPos < filenameStart || dotPos == path.length() - 1) {
            return ""; // 无扩展名或点在目录中
        }

        return path.substr(dotPos + 1); // 返回不带点的扩展名
#endif
    } 
    
    std::string GetFilenameWithoutExtension(const std::string &path)
    {
#ifndef CXX_LESS_17
        if (path.empty()) {
            return "" ;
        }
        return std::filesystem::path(path).stem().string();
#else
        // 获取文件名起始位置（最后一个 / 或 \ 之后）
        size_t slashPos = path.find_last_of("/\\");
        size_t start = (slashPos == std::string::npos) ? 0 : slashPos + 1;

        // 获取扩展名前的位置（最后一个点）
        size_t dotPos = path.find_last_of('.');

        // 点如果在文件名部分之外（例如在目录名中），忽略
        if (dotPos == std::string::npos || dotPos < start) {
            dotPos = path.length();
        }

        return path.substr(start, dotPos - start);
#endif
    }

    std::string GetExtension(const std::string &path)
    {
#ifndef CXX_LESS_17
        return StringUtil::ToLowerCase(std::filesystem::path(path).extension().string());
#else
        // 找最后一个斜杠（表示路径分隔）
        size_t slashPos = path.find_last_of("/\\");
        size_t dotPos = path.find_last_of('.');

        // 点不存在或在路径前面，说明没有扩展名
        if (dotPos == std::string::npos || (slashPos != std::string::npos && dotPos < slashPos)) {
            return "";
        }

        return path.substr(dotPos);
#endif
    }

    bool IsFileExist(const std::string &path)
    {
#ifndef CXX_LESS_17
        return std::filesystem::exists(path) && std::filesystem::is_regular_file(path);
#else 
        struct stat buffer;
        return (stat(path.c_str(), &buffer) == 0); // 如果返回0，路径存在
#endif
    }

    bool IsDirExist(const std::string &path)
    {
#ifndef CXX_LESS_17
        return std::filesystem::exists(path) && std::filesystem::is_directory(path);
#else
        struct stat buffer;
        // 检查路径是否存在且是一个目录
        if (stat(path.c_str(), &buffer) == 0) {
            return S_ISDIR(buffer.st_mode);  // 判断是否是目录
        }
        return false;  // 如果路径不存在或不是目录
#endif
    }
#ifndef CXX_LESS_17
    void TraverseDirectory(const std::filesystem::path &path, std::vector<std::string> *containers)
    {
        for (const auto &entry : std::filesystem::directory_iterator(path))
        {
            if (entry.is_directory())
            {
                TraverseDirectory(entry.path(), containers); // 递归遍历子目录
            }
            else
            {
                containers->emplace_back(entry.path().string());
            }
        }
    }
#endif

    std::string GetParentPath(const std::string &path)
    {
#ifndef CXX_LESS_17
        return std::filesystem::path(path).parent_path().string();
#else
        size_t lastSlashPos = path.find_last_of("/\\");
        if (lastSlashPos == std::string::npos) {
            return ""; // 没有父目录
        }
        return path.substr(0, lastSlashPos);
#endif
    } 

    
#ifdef CXX_LESS_17
    // 分割路径为各个部分
    static std::vector<std::string> splitPath(const std::string& path) {
        std::vector<std::string> parts;
        size_t start = 0;
        size_t end = path.find('/');

        while (end != std::string::npos) {
            std::string part = path.substr(start, end - start);
            if (!part.empty()) {
                parts.push_back(part);
            }
            start = end + 1;
            end = path.find('/', start);
        }
        std::string lastPart = path.substr(start);
        if (!lastPart.empty()) {
            parts.push_back(lastPart);
        }

        return parts;
    }

    // 构建规范化路径（不检查文件是否存在）
    static std::string normalizePath(const std::vector<std::string>& parts) {
        std::vector<std::string> stack;

        for (const auto& part : parts) {
            if (part == ".") {
                continue;  // 忽略当前目录
            } else if (part == "..") {
                if (!stack.empty()) {
                    stack.pop_back();  // 返回上一级目录
                }
            } else {
                stack.push_back(part);  // 普通目录
            }
        }

        std::string result;
        for (const auto& part : stack) {
            result += "/" + part;
        }

        return result.empty() ? "/" : result;
    }

    // 获取绝对路径（不检查文件是否存在）
    static std::string getAbsolutePathImpl(const std::string& inputPath) {
        if (inputPath.empty()) {
            std::cerr << "错误: 路径为空" << std::endl;
            return "";
        }

        if (inputPath[0] == '/') {
            // 绝对路径，直接规范化
            return normalizePath(splitPath(inputPath));
        } else {
            // 相对路径，结合当前工作目录
            char cwd[PATH_MAX];
            if (getcwd(cwd, PATH_MAX) == nullptr) {
                std::cerr << "错误: 无法获取当前工作目录" << std::endl;
                return "";
            }
            std::string fullPath = std::string(cwd) + "/" + inputPath;
            return normalizePath(splitPath(fullPath));
        }
    }
#endif

    std::string GetAbsolutePath(std::string p)
    {
        #ifndef CXX_LESS_17
            std::string absolutePath = p;
            std::filesystem::path path(p) ;
            if (!path.is_absolute()) {
                absolutePath = std::filesystem::absolute(path).string() ;
            }
            return absolutePath ;
        #else
            return getAbsolutePathImpl(p);
        #endif
    }
}

AMCAX_EXCHANGE_NAMESPACE_END